<template>
	<view class="collect">
		<view class="map-box">
			<view id="olMap" class="olMap" :prop="control" :change:prop="ol.updateMap" @click="ol.sendPos"></view>
			<search :position="position" @sendPos="receivePo"></search>
			<detail :event="event" :show.sync="isOPen"></detail>
			<formbar :position="position" @reLocation="reLocation" @getsatellite="getsatellite" @finish="refreshMap"></formbar>
		</view>
	</view>
</template>

<script>
	import {getLocation, reverseGeocode, deepClone, gcj02towgs84, wgs84togcj02, formatDate} from '@/util/util.js';
	import {getReLocation, queryAreaByXy} from '../../util/api.js'
	import Formbar from '@/pages/collect/formbar.vue';
	import Search from '@/pages/collect/search.vue';
	import Detail from '@/pages/collect/detail.vue';
	  
	export default {
		components: {
			Formbar,
			Search,
			Detail
		},
		data() {
			return {
				mapWidth: '',
				mapHeight: '',
				keyword: '',
				address: '地址',
				latitude: '',   //维度 y
				longitude: '', //经度 x
				map: null,
				control: {location: '', events: []},
				position: {},
				satellite: '',
				reLocationStartTime: null,
				events: [],
				event: {},
				isOPen: false,
				userInfo: {},
				loopNum: 0,
				timer: null,
				delayedTimer: null,
				rePos: {}
			}
		},
		methods: {
			async createPos(pos = {}){
				let control = {
					events: []
				};
				
				let position = {};
				
				if(Object.keys(pos).length > 0){
					control.location = [this.longitude, this.latitude];
					
					position = {
						address: this.address,
						longitude: this.longitude,
						latitude: this.latitude,
						satellite: pos.satellite
					};
				} else {
					control.location = gcj02towgs84(this.longitude, this.latitude);
					
					position = {
						address: this.address,
						longitude: control.location[0],
						latitude: control.location[1],
						satellite: pos.satellite || ''
					};
				}
				
				let params = {
					x: position.longitude,
					y: position.latitude
				};
				
				let {data: {facilityData: events}} = await queryAreaByXy(params);
				
				control.events = events;
				
				this.position = deepClone(position);
				this.control = deepClone(control);
			},
			receivePo({point, address}) {
				this.longitude = point.longitude;
				this.latitude = point.latitude;
				this.address = address;
				
				this.createPos();
			},
			async getLocation() {
				let res = await getLocation();
				
				if (res.latitude && res.longitude) {
					this.longitude = res.longitude;
					this.latitude = res.latitude;
					this.address = res.address ? `${res.address.city}${res.address.district}${res.address.street}${res.address.streetNum}` : '地址';
				}
				
				this.createPos();
			},
			async getReLocation(cycle = false) {
				if(this.timer){
					clearTimeout(this.timer);
					this.timer = null;
				}
				
				uni.showLoading({
					title: '获取定位中...',
					mask: true
				});
				
				if(cycle){
					await this.cycle();
				}
				
				let position = {};
				
				let params = {
					page: 1,
					limit: 1,
					precision: 5
				}
				
				if(this.userInfo.deivceNum) params.deviceId = this.userInfo.deivceNum;
				
				if(this.reLocationStartTime == null) this.reLocationStartTime = formatDate(new Date().getTime());
				
				params.startTime = this.reLocationStartTime;
				
				let {data: positions} = await getReLocation(params);
				
				uni.hideLoading({
					mask: true
				});
				
				if(positions.length == 0) {
					this.loopNum = this.loopNum + 1;
					
					if( this.loopNum >= 6) {
						uni.showToast({
						  title: '暂时没有地位数据，请稍后再试。',
						  icon: 'none',
						  duration: 2000,
						  mask: true
						});
						
						this.loopNum = 0;
					} else {
						uni.showToast({
						  title: `没有定位数据，正在重试第${this.loopNum + 1}次获取定位数据`,
						  icon: 'none',
						  duration: 1000,
						  mask: true
						});
						
						this.timer = setTimeout(this.getReLocation.bind(this, true), 1000);
					}
				} else {
					position = deepClone(positions[0]);
					this.reLocationStartTime == null;
					
					if(this.timer){
						clearTimeout(this.timer);
						this.timer = null;
					}
					
					if(this.delayedTimer){
						clearTimeout(this.delayedTimer);
						this.delayedTimer = null;
					}
					
					this.rePos = position;
				}
			},
			async cycle(){
				return await new Promise((resolve, reject) => {
					this.delayedTimer = setTimeout(() => {
						resolve();
					}, 5000);
				})
			},
			async getsatellite(){
				let params = {
					deviceId: this.userInfo.deivceNum,
					page: 1,
					limit: 1
				};
				
				params.startTime = formatDate(new Date().getTime());
				
				let {data: positions} = await getReLocation(params);
				
				if(positions.length > 0){
					this.position['satellite'] = positions[0]['satellite'];
				}
			},
			async reLocation() {
				if(this.timer){
					return 
				}
				
				await this.getReLocation();
				
				let position = this.rePos;
				
				if(Object.keys(position).length == 0) {
					return;
				} else {}
				
				let params = {
					x: position.longitude,
					y: position.latitude
				};
				
				let cood = wgs84togcj02(params.x, params.y);
				let { address } = await reverseGeocode(cood[0], cood[1]);
				
				this.address = address;
				this.longitude = position.longitude;
				this.latitude = position.latitude;
				
				this.createPos(position);
			},
			refreshMap() {
				this.reLocationStartTime = null;
			},
			async initMap() {},
			receivePos(pos) {
				let event = this.control.events.find(event => event.facilityData.find( facility => pos.facilityId == facility.id))
				
				this.event = deepClone(event);
				this.isOPen = true;
			},
			async init() {
				this.userInfo = await uni.getStorageSync('userInfor');
				await this.getLocation();
				this.initMap();
			}
		},
		onLoad() {},
		onUnload(){
			if(this.timer){
				clearTimeout(this.timer);
				this.timer = null;
			}
			
			if(this.delayedTimer){
				clearTimeout(this.delayedTimer);
				this.delayedTimer = null;
			}
		},
		onReady() {
			this.init();
		}
	}
	
</script>
<script module="ol" lang="renderjs">
	import "@/static/ol/ol.css";
	export default{
		data() {
			return {
				pictureUrl: 'http://3x5a603746.qicp.vip:55690',
				latitude: '', //维度 y
				longitude: '',//经度 x,
				locationLayer: null,
				eventsLayer: null,
				facilityId: '',
				timer: null,
			}
		},
		methods: {
			cycle(callback) {
				if(this.timer){
					clearInterval(this.timer);
				}
				
				if (typeof window.ol === 'object'){
					callback();
				} else {
					this.timer = setTimeout(this.cycle.bind(this,callback), 1000)
				}
			},
			async initOlMap() {
				this.setMapCenter();
				this.drawEventsPoint();
				this.drawLoactionPoint();
			},
			async updateMap(newValue, oldValue, ownerInstance, instance) {
				this.cycle(this.initOlMap.bind(this));
			},
			drawMap() {	
				let layers = [
					new ol.layer.Tile({
						source: new ol.source.XYZ({
							projection: 'EPSG:4326',
							url: `${this.pictureUrl}/getlayer?x={x}&y={y}&z={z}&inputdate=2021-09-26&zoom=1&layer=xiann_google_layer`
						})
					}),
					new ol.layer.Tile({
						source: new ol.source.XYZ({
							url: `${this.pictureUrl}/getlayer?x={x}&y={y}&z={z}&inputdate=2021-08-25&layer=qujiang_layer&zoom=1`
						})
					}),
					new ol.layer.Tile({
						source: new ol.source.XYZ({
						    url: `${this.pictureUrl}/getlayer?x={x}&y={y}&z={z}&inputdate=2021-08-20&layer=gaoxin_layer&zoom=1`
						})
					}),
					new ol.layer.Tile({
						source: new ol.source.XYZ({
							url: `${this.pictureUrl}/getlayer?x={x}&y={y}&z={z}&inputdate=2021-08-20&layer=gaoxin_layer&zoom=2`
						})
					}),
					new ol.layer.Tile({
						source: new ol.source.XYZ({
							url: `${this.pictureUrl}/getlayer?x={x}&y={y}&z={z}&inputdate=2021-08-20&layer=gaoxin_layer&zoom=3`
						})
					})
				];
				
				this.map = new ol.Map({
					layers,
					target: 'olMap',
					logo: false,
					controls: ol.control.defaults({
						attribution: false,
					    rotate: false,
					    zoom: false
					})
				});
				
				this.map.on('click', (e) => {
					this.facilityId = '';
					
					let feature = this.map.forEachFeatureAtPixel(e.pixel, feature => feature);
					
					if (feature && feature['A']['id']) {
						this.facilityId = feature['A']['id'];
					}
				});
			},
			setMapCenter(){
				this.map.setView(new ol.View({
					center: this.control.location,
					projection: new ol.proj.Projection({
					    code: 'EPSG:4326',
					    units: 'degrees',
					    axisOrientation: 'neu'
					}),
					zoom: 18,
					minZoom: 10,
					maxZoom: 22
				}))
			},
			drawLoactionPoint() {
				// 新建图层，用于标记中心点
				if(this.locationLayer !== null){
					this.map.removeLayer(this.locationLayer);
					this.locationLayer = null;
				}
				 
				// openlayers点对象
				let locationPoint = new ol.geom.Point(this.control.location);
				let locationFeature = new ol.Feature({type: 'point'});
				
				// 设置几何图形
				locationFeature.setGeometry(locationPoint);
				
				let locationVector = new ol.source.Vector();
				
				// 设置图层属性
				locationVector.addFeature(locationFeature);
				
				this.locationLayer = new ol.layer.Vector();
				this.locationLayer.setSource(locationVector);
				
				// style样式的使用，icon图标
				let centerPointStyle = new ol.style.Style({
					image: new ol.style.Icon({
						src: 'static/images/icon_location.png',
						anchor: [0.5, 1],
					})
				});
				
				this.locationLayer.setStyle(centerPointStyle);
				this.map.addLayer(this.locationLayer);
			},
			drawEventsPoint() {
				if(this.eventsLayer !== null){
					this.map.removeLayer(this.eventsLayer);
					this.eventsLayer = null;
				}
				
				let locationVector = new ol.source.Vector();
				
				if(this.control.events.length == 0) return ;
				
				this.control.events.forEach( event => {
					event['facilityData'].forEach( facility => {
						let coordinates = JSON.parse(facility['grid'])['coordinates']
						let facilityId = facility['id'];
						let locationPoint = new ol.geom.Point(coordinates);
						let locationFeature = new ol.Feature({type: 'point', id: facilityId});
						
						locationFeature.setGeometry(locationPoint);
						locationVector.addFeature(locationFeature);
					})
				})
				
				this.eventsLayer = new ol.layer.Vector();
				this.eventsLayer.setSource(locationVector);
				
				let centerPointStyle = new ol.style.Style({
					image: new ol.style.Icon({
						src: 'static/images/icon_location2.png',
						anchor: [0.5, 1],
					})
				});
				
				this.eventsLayer.setStyle(centerPointStyle);
				
				this.eventsLayer.setStyle(centerPointStyle);
				this.map.addLayer(this.eventsLayer);
			},
			sendPos(event, ownerInstance) {
				setTimeout(() => {
					if(this.facilityId){
						ownerInstance.callMethod('receivePos', {
							facilityId: this.facilityId
						})
					}
				},500)
			},
			initOl() {
				if (typeof window.ol === 'object') {
					this.drawMap();
				} else {
					const script = document.createElement('script');
					script.src = './static/ol/ol.js';
					script.onload = this.drawMap.bind(this);
					document.head.appendChild(script);
				}
			}
		},
		created() {
			this.initOl();
		},
		mounted() {
			
		}
	}
</script>

<style lang="scss">
	.collect {
		position: absolute;
		top: 0rpx;
		right: 0rpx;
		bottom: 0rpx;
		left: 0rpx;
	}

	.map-box {
		position: absolute;
		top: 0px;
		right: 0px;
		bottom: 0px;
		left: 0px;
	}

	.olMap {
		position: absolute;
		top: 0px;
		right: 0px;
		bottom: 0px;
		left: 0px;
	}
</style>
